package org.apereo.cas.web.flow.login;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apereo.cas.CentralAuthenticationService;
import org.apereo.cas.web.flow.SingleSignOnParticipationStrategy;
import org.apereo.cas.web.support.CookieRetrievingCookieGenerator;
import org.apereo.cas.web.support.WebUtils;
import org.springframework.webflow.action.AbstractAction;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;

/**
 * Action that handles the TicketGrantingTicket creation and destruction. If the
 * action is given a TicketGrantingTicket and one also already exists, the old
 * one is destroyed and replaced with the new one. This action always returns
 * "success".
 *
 * @author Scott Battaglia
 * @since 3.0.0
 */
@Slf4j
@RequiredArgsConstructor
/*xxx: 发送tgt动作*/
public class SendTicketGrantingTicketAction extends AbstractAction {
    private final CentralAuthenticationService centralAuthenticationService;
    private final CookieRetrievingCookieGenerator ticketGrantingTicketCookieGenerator;
    private final SingleSignOnParticipationStrategy renewalStrategy;

    @Override
    protected Event doExecute(final RequestContext context) {
        /*xxx: 从请求上下文中，获取tgtId信息 */
        final String ticketGrantingTicketId = WebUtils.getTicketGrantingTicketId(context);
        /*xxx: 从cookie中，获取tgtId信息 */
        final String ticketGrantingTicketValueFromCookie = WebUtils.getTicketGrantingTicketIdFrom(context.getFlowScope());
        /*xxx: 如果上下文中，没有tgt信息，则直接返回成功*/
        if (StringUtils.isBlank(ticketGrantingTicketId)) {
            log.debug("No ticket-granting ticket is found in the context.");
            return success();
        }
        /*xxx: 如果认证信息是 公共工作区的话，则不生成 tgt*/
        if (WebUtils.isAuthenticatingAtPublicWorkstation(context)) {
            log.info("Authentication is at a public workstation. SSO cookie will not be generated. Requests will be challenged for authentication.");
        } else if (this.renewalStrategy.isParticipating(context)) { /*xxx: 是否允许更新tgt*/
            log.debug("Setting ticket-granting cookie for current session linked to [{}].", ticketGrantingTicketId);
            this.ticketGrantingTicketCookieGenerator.addCookie(context, ticketGrantingTicketId);
        } else {
            log.info("Authentication session is renewed but CAS is not configured to create the SSO session. "
                + "SSO cookie will not be generated. Subsequent requests will be challenged for credentials.");
        }
        /*xxx: 如果cookie中的tgc，与当前上下文中的 tgtId不匹配，则需要进行销毁 tgt*/
        if (ticketGrantingTicketValueFromCookie != null && !ticketGrantingTicketId.equals(ticketGrantingTicketValueFromCookie)) {
            log.debug("Ticket-granting ticket from TGC does not match the ticket-granting ticket from context");
            this.centralAuthenticationService.destroyTicketGrantingTicket(ticketGrantingTicketValueFromCookie);
        }

        return success();
    }
}
